//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <mantle.h>

PInterface CObjectEnumerator::Probe(
    /* [in] */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (PInterface)(IObjectEnumerator *)this;
    }
    else if (riid == EIID_IObjectEnumerator) {
        return (IObjectEnumerator *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CObjectEnumerator;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface)&EIID_IObjectEnumerator;
    }

    return NULL;
}

UInt32 CObjectEnumerator::AddRef(void)
{
    return m_cRef.Increment();
}

UInt32 CObjectEnumerator::Release(void)
{
    Int32 lRef = m_cRef.Decrement();

    assert(lRef >= 0);

    if (0 == lRef) {
        delete this;
    }
    return (UInt32)lRef;
}

ECode CObjectEnumerator::Aggregate(
    /* [in] */ AggregateType type,
    /* [in] */ PInterface pObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CObjectEnumerator::GetDomain(
    /* [out] */ PInterface *ppObj)
{
    return E_NOT_IMPLEMENTED;
}

ECode CObjectEnumerator::Current(
    /* [out] */ PInterface *ppObject)
{
    if (NULL == ppObject) return E_INVALID_ARGUMENT;

    m_pListLock->Lock();

    if (NULL == m_pCurrentNode || m_pListHead == m_pCurrentNode) {
        m_pListLock->Unlock();
        return E_INVALID_OPERATION;
    }

    if (m_nOrgListState != *m_pListState) {
        m_pCurrentNode = NULL;
        m_pListLock->Unlock();
        return E_INVALID_OPERATION;
    }

    DzDisablePreemption();
    if (0 == ((ObjectEnumeratorNode *)m_pCurrentNode)->m_cRef) {
        EnablePreemption();
        m_pListLock->Unlock();
        return E_INVALID_OPERATION;
    }

    *ppObject = ((ObjectEnumeratorNode *)m_pCurrentNode)->GetObject();
    (*ppObject)->AddRef();
    EnablePreemption();
    m_pListLock->Unlock();

    return NOERROR;
}

ECode CObjectEnumerator::MoveNext(Boolean *pSucceeded)
{
    if (NULL == pSucceeded) {
        return E_INVALID_ARGUMENT;
    }

    m_pListLock->Lock();

    if (NULL == m_pCurrentNode) {
        *pSucceeded = FALSE;
        m_pListLock->Unlock();
        return E_INVALID_OPERATION;
    }

    if (m_nOrgListState != *m_pListState) {
        m_pCurrentNode = NULL;
        m_pListLock->Unlock();
        *pSucceeded = FALSE;
        return E_INVALID_OPERATION;
    }

    if (m_pCurrentNode == m_pListHead->m_pPrev) {
        m_pCurrentNode = NULL;
        m_pListLock->Unlock();
        *pSucceeded = FALSE;
        return NOERROR;
    }
    else {
        m_pCurrentNode = m_pCurrentNode->m_pNext;
        m_pListLock->Unlock();
        *pSucceeded = TRUE;
        return NOERROR;
    }
}

ECode CObjectEnumerator::Reset()
{
    m_pListLock->Lock();
    m_pCurrentNode = m_pListHead;
    m_nOrgListState = *m_pListState;
    m_pListLock->Unlock();
    return NOERROR;
}
